﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.ServiceModel;
using System.Text;

namespace Tradex.Connectivity {
    
    /// <summary>
    /// This class generates proper ConnectorApi local instances that can contact the remote
    /// central ConnectorApi.
    /// </summary>
    public sealed class ConnectivityApiFactory : IDisposable  {

        /// <summary>
        /// Constructor for the Factory.
        /// </summary>
        public ConnectivityApiFactory() {
            _Factory = new ChannelFactory<IConnectivityApi>(
                new NetNamedPipeBinding(NetNamedPipeSecurityMode.None) { MaxReceivedMessageSize = 65536 * 64 },
                new EndpointAddress(ConnectivityApiHost.GetConnectivityUrl ())
            );
        }

        ChannelFactory<IConnectivityApi> _Factory;

        /// <summary>
        /// Generates a new IConnectorApi channel.
        /// </summary>
        /// <returns></returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
        public IConnectivityApi GetChannel() {
            return _Factory.CreateChannel();
        }

        /// <summary>
        /// Disposes a channel.
        /// </summary>
        /// <param name="channel"></param>
        public void DisposeChannel (IConnectivityApi channel) {
            if (channel == null) {
                throw new ArgumentException("value can not be null", "channel");
            }
            Contract.EndContractBlock();

            IClientChannel clientChannel = channel as IClientChannel;
            if (channel == null) {
                throw new ArgumentException("value is not a wcf client channel", "channel");
            }
            clientChannel.Abort();
            if (clientChannel.State != CommunicationState.Faulted) {
                clientChannel.Dispose();
            }
        }

        /// <inheritdoc />
        public void Dispose() {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        void Dispose(bool disposing) {
            if (disposing) {
                if (_Factory != null) {
                    ((IDisposable)_Factory).Dispose();
                    _Factory = null;
                }
            }
        }
    }

}
